<template>
  <div class="overview-wrap">
    <div class="terms">
      <el-form ref="queryForm" class="query-form" :model="queryParams" inline>
      <el-form-item label="项目" prop="app_id">
        <el-select size="small" style="width: 150px;" v-model="queryParams.app_id" @change="proChange">
          <el-option v-for="item in permission_projectList" :value="item.app_id" :label="item.name" :key="item.app_id"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="指标" prop="indicator">
        <indic-cascader v-model="queryParams.indicator" :options="indicatorOpts" :defIndic="defIndicator" @change="indicatorChange" />
      </el-form-item>
      <el-form-item label="权益包" prop="attr_id">
        <select-check-box v-model="queryParams.attr_id" :selOptions="packageOpts" checkAllLabel="全部业务"/>
      </el-form-item>
      <el-form-item label="渠道" prop="union_id">
        <select-check-box  v-model="queryParams.union_id" :selOptions="channelOpts" :props="{value:'channel_id',label:'name'}" doubleColumn checkAllLabel="全部渠道" filterable>
        </select-check-box>
      </el-form-item>
      <el-form-item label="版本" prop="version">
        <version-select ref="versionSelect" :selOptions="versionOpts" isIntVer v-model="queryParams.version"></version-select>
      </el-form-item>
      <el-form-item>
        <el-button type="primary"
          size="small"
          @click="init">搜索</el-button>
      </el-form-item>
    </el-form>
    </div>
    <div class="scroll">
      <!-- 时间分层趋势图 -->
      <div ref="section2" class="section section2">
        <div class="headline">
          <h5 class="title">
            时间分层趋势图</h5>
          <span class="full-screen">
            <!-- <Screenfull :taget="$refs.section2" @change="screenChange($event,2)"/> -->
          </span>
        </div>
        <div class="condition">
          <div class="date-filter">
            <span class="label">选择时间范围</span>
            <date-range :dateRange.sync="queryParams2.time_range" :dateType.sync="queryParams2.time_grain_sqla" :append-to-body="!isFullScreen" @dateTypeChange="dateTypeChange" @change="renderChartLayer(true)" />
          </div>
          <div style="margin-top:5px;text-align: right;">
            对比：前
            <el-input-number v-model="timeRangeNum" size="mini" controls-position="right" @change="timeRangeNumChange" :min="1" :max="9999"></el-input-number>
            {{ queryParams2.time_grain_sqla==='P1D'?'天':queryParams2.time_grain_sqla==='P1W'?'周':'月' }}
          </div>
        </div>
        <div class="content">
          <div class="chart-wrap" v-loading="loading5">
            <double-line-chart class="chart" :listData="chartData2" :legend="legendData2" :params="chartparams2" :timeRangeNum="timeRangeNum" @legendChang="legendChang"/>
          </div>
        </div>
        <div style="margin-top:20px">
          <div v-for="(unionGroup,index) in unionGroupData" :key="index">
          <span>{{ unionGroup.name }}：</span>
          <span v-for="item in unionGroup.value" :key="item.union_id" class="ml10">
            <span>{{ item.union_id }}：</span>
            <span>{{formatNumber(item[unionGroup.name],unionGroup.name)}}{{unionGroup.name.endsWith('率') ? '%' : ''}}</span>
          </span>
          <!-- <el-button style="margin-left:20px" type="text" @click="toChannelAnal">查看详情</el-button> -->
        </div>
        </div>
      </div>
      <div>
      </div>
      <!-- 指标概览 -->
      <div class="section section1">
        <div class="headline">
          <h5 class="title">
            指标概览</h5>
          <ul class="patterns">
            <li class="pattern" v-for="item in patternOpts" :key="item.value" :class="{active:pattern === item.value}" :title="item.title" @click="togglePattern(item)">
              <svg-icon :iconClass="item.icon" />
            </li>
          </ul>
        </div>
        <div class="condition">
            <el-button class="export" size="small" v-show="pattern === 2" icon="el-icon-download" :loading="btnLoading1" @click="exportExcel1">导出Excel</el-button>
          <div class="date-filter">
            <span class="label">选择时间</span>
            <el-date-picker size="small" v-model="queryParams1.time_range" type="date" placeholder="选择日期" :clearable="false" value-format="yyyy-MM-dd" :picker-options="pickerOptions" @change="renderViewLayer(true)">
            </el-date-picker>
          </div>
        </div>
        <div class="content" v-loading="loading1">
          <div class="card-wrap" v-show="pattern === 0">
            <div ref="cardList" class="card-list" :class="{fold: isFold}">
              <div class="card-box" v-for="(item,index) in cardList" :key="index">
                <div class="card-top">
                  <span class="title" @click="indicatorDetail(item)">{{item.title}}</span>
                  <el-tooltip :content="item.describe">
                    <i class="el-icon-warning-outline"></i>
                  </el-tooltip>
                </div>
                <h5 class="count">{{fmtNumer(item.count,item.title)}}</h5>
                <div class="trend">
                  <el-tooltip :content="!isNumber(item.prevDay)?'暂无数据':`上一日（${formatDate(yesterday,'{m}/{d}')}）${item.title}为${fmtNumer(item.prevCount,item.title)}，相比${item.prevDay > 0?'增长':'降低'}${Math.abs(item.prevDay)}%`">
                    <div class="trend_item prevDay">
                      <span class="label">环比</span>
                      <span v-show="isNumber(item.prevDay)" class="rise" :class="{decline:item.prevDay < 0}"></span>
                      <span>{{fmtNumer(item.prevDay,true)}}</span>
                    </div>
                  </el-tooltip>
                  <el-tooltip :content="!isNumber(item.prevWeek)?'暂无数据':`上周今日（${formatDate(lastWeek,'{m}/{d}')}）${item.title}为${fmtNumer(item.lastCount,item.title)}，相比${item.prevWeek>0?'增长':'降低'}${Math.abs(item.prevWeek)}%`">
                    <div class="trend_item prevWeek">
                      <span class="label">同比</span>
                      <span v-show="isNumber(item.prevWeek)" class="rise" :class="{decline:item.prevWeek < 0}"></span>
                      <span>{{fmtNumer(item.prevWeek,true)}}</span>
                    </div>
                  </el-tooltip>
                </div>
                <div class="average">
                  <div class="last-week">
                    <span>近 7天日均</span>
                    <span class="num">{{fmtNumer(item.average7,item.title)}}</span>
                  </div>
                  <div class="last-month">
                    <span>近30天日均</span>
                    <span class="num">{{fmtNumer(item.average30,item.title)}}</span>
                  </div>
                </div>
              </div>
            </div>
            <div v-show="foldBtnShow" class="fold-box">
              <span class="fold" @click="isFold=!isFold">
                {{isFold?'展开':'收起'}}
                <span class="mark" :class="{fold:isFold}"></span>
              </span>
            </div>
          </div>
          <div class="chart-wrap" v-show="pattern === 1">
            <double-line-chart class="chart" v-loading="loading4" :listData="chartData1" :legend="legendData1" :params="chartparams1" />
          </div>
          <div class="table-wrap" v-show="pattern === 2">
            <tableList className="scroll" :data="tableList1" :columns="tableKeys1" :max-height="400" :showMark="false" :row-class-name="rowClassName" @sort-change="sortChange($event,1)" />
          </div>
        </div>
      </div>
      <!-- 时间分层数据表 -->
      <div ref="section3" class="section section3" style="margin-bottom: 0;">
        <div class="headline">
          <h5 class="title">
            时间分层数据表
            <span class="export" @click="exportExcel2">
              <svg-icon iconClass="export" />
            </span>
            <span class="tips">（当表格中某行被选中，可直接采用“↑”“↓”“←”“→”来移动表格）</span>
          </h5>
          <span class="full-screen">
            <!-- <Screenfull :taget="$refs.section3" @change="screenChange($event,3)" /> -->
          </span>
        </div>
        <div class="condition">
          <div class="date-filter">
            <span class="label">选择时间范围</span>
            <date-range :dateRange.sync="queryParams3.time_range" :dateType.sync="queryParams3.time_grain_sqla" :append-to-body="!isFullScreen" @change="renderTableLayer" @dateTypeChange="renderTableLayer"/>
          </div>
        </div>
        <div ref="content3" class="content" v-loading="loading3">
          <div class="table-wrap">
            <table-list ref="tableWrap" className="scroll" :data="tableList2" :columns="tableKeys2" :showMark="false" :cell-class-name="cellClassName" :row-class-name="rowClassName2" :max-height="700" @headerClick="viewDetails" @sort-change="sortChange($event,2)"/>
          </div>
        </div>
      </div>
      <indicator-detail :visible.sync="detail.visible" :params="detail.params" :indicator="detail.indicator" :packageOpts="packageOpts" :channelOpts="channelOpts" />
      <indic-particular :visible.sync="particular.visible" :params="particular.params" :indicator="particular.indicator" :packageOpts="packageOpts" :channelOpts="channelOpts" />
    </div>
  </div>
</template>

<script type="text/javascript">
import Mixin from './mixin'
import Axios from 'axios'
import { mapGetters } from 'vuex'
import { getIndicators, getReportDatas } from '@/api/report/index'
import { getVersionTree } from '@/api'
import { getRightPackage, listRightPackage } from '@/api/rights/package'
import { getOverview } from '@/utils/database'
import { parseTime, debounce, toFixed, numToText, isNumber } from '@/utils/index'
// import Screenfull from '@/components/Screenfull'
import IndicatorDetail from './components/indicatorDetail.vue'
import IndicParticular from './components/indicParticular.vue'
import DateRange from './components/dateRange'
import IndicCascader from './components/indicCascader.vue'
import TableList from './components/tableList.vue'
import DoubleLineChart from './components/doubleLineChart.vue'
import { getReportData } from '@/api/report/overview'
import * as exportDoc from '@/utils/exportDoc'
import { getChannelByAppId } from '@/api/system/channel'

import { DATE_TYPE, EXINDICATORS } from './constant'
const defIndicator = ['交易总额', '交易笔数', '交易笔单价', '交易客单价', '安装用户数', '活跃用户数', '注册用户数', '付费用户数', '安装注册率', '安装付费率', '注册付费率', '卸载用户数', '月活', '安装卸载率']
const dateFmt = '{y}-{m}-{d}'
export default {
  name: 'Overview',
  mixins: [Mixin],
  components: {
    IndicatorDetail,
    // Screenfull,
    DateRange,
    IndicCascader,
    IndicParticular,
    TableList,
    DoubleLineChart
  },
  props: {},
  data () {
    const d = new Date()
    d.setDate(d.getDate() - 1)
    const end = parseTime(d, dateFmt)
    const start = parseTime(d.setDate(d.getDate() - 14), dateFmt)
    const indicator = localStorage.getItem('indicator')
    return {
      pattern: 0,
      loading1: false,
      timeRangeNum: 7,
      timeRangeNumD: 7,
      timeRangeNumW: 1,
      timeRangeNumM: 1,
      queryParams: {
        app_id: '',
        indicator: indicator ? JSON.parse(indicator) : [-1],
        union_id: [],
        attr_id: [],
        time_grain_sqla: DATE_TYPE.DAY,
        version: []
      },
      queryParams1: {
        time_range: end
      },
      queryParams2: {
        time_range: [start, end],
        time_grain_sqla: DATE_TYPE.DAY
      },
      queryParams3: {
        time_range: [start, end],
        order_by: 'time desc',
        time_grain_sqla: DATE_TYPE.DAY
      },
      cardList: [], // 概览列表
      isFold: true,
      foldBtnShow: false,
      detailVisible: false,
      indicator: {},
      tableList1: [],
      tableKeys1: [],
      tableList2: [], // 表格数据
      tableKeys2: [], // 表格表头
      chartData1: [], // 折线图数据
      chartparams1: {},
      legendData1: [], // 折线图图例
      chartData2: [],
      chartparams2: {},
      legendData2: [],
      unionGroupData: [],
      patternOpts: [{
        icon: 'card',
        value: 0,
        title: '卡片组'
      }, {
        icon: 'line-chart',
        value: 1,
        title: '折线图'
      }, {
        icon: 'table-2',
        value: 2,
        title: '数据表'
      }],
      indicatorOpts: [],
      allpackages: [], // 权益包
      channelOpts: [],
      cascaderProps: { multiple: true, emitPath: false },
      detail: {
        indicator: {},
        params: {},
        visible: false
      },
      particular: {
        indicator: {},
        params: {},
        visible: false
      },
      btnLoading1: false,
      loading3: false,
      loading4: false,
      loading5: false,
      maxHeight: 700,
      isFullScreen: false, // 是否全屏
      pickerOptions: {
        disabledDate (time) {
          return time.getTime() > new Date().setHours(0, 0, 0, 0)
        }
      },
      versionOpts: []
    }
  },
  async mounted () {
    const resizeHandler = debounce(() => {
      this.setFoldBtnShow()
    })
    this.legendList = ['交易总额', '活跃用户数']
    window.addEventListener('resize', resizeHandler)
    this.$once('hook:beforeDestroy', () => {
      window.removeEventListener('resize', resizeHandler)
    })
    this.maxHeight = this.$el.offsetHeight - 100
    await Axios.all([getIndicators()]).then(Axios.spread((res1) => {
      const indicatorOpts = [
        {
          value: -1,
          label: '默认'
        }
      ]
      const indicatorMap = new Map()
      this.indicatorSort(res1.data).map(item => {
        const obj = {
          category: item.category,
          value: item.ID,
          label: item.name,
          describe: item.describe,
          totalHide: EXINDICATORS.includes(item.name) // 隐藏总数数据展示
        }
        const it = indicatorOpts.find(t => t.label === obj.category)
        indicatorMap.set(item.name, item)
        if (it) {
          it.children.push(obj)
        } else {
          indicatorOpts.push({
            value: -indicatorOpts.length - 1,
            label: obj.category,
            children: [obj]
          })
        }
      })
      this.indicatorMap1 = indicatorMap
      this.indicatorOpts = indicatorOpts
      // 获取所有权益包
      this.getAllRights()
    }))
    await this.getChannels()
    if (this.permission_projectList.length) {
      this.queryParams.app_id = this.permission_projectList[0].app_id
      this.proChange(this.queryParams.app_id)
    }
    this.metricsGroup = await getOverview()
    this.init()
  },
  methods: {
    async init () {
      await this.renderChartLayer()
      await this.renderViewLayer()
      this.renderTableLayer()
    },
    proChange (val) {
      this.channelOpts = this.channelList.filter(item1 => item1.app_id === this.queryParams.app_id)
      this.getVerLists(val)
      this.queryParams.union_id = []
      this.queryParams.attr_id = []
      this.queryParams.version = []
    },
    renderViewLayer () {
      const { pattern } = this
      this.loading1 = false
      switch (pattern) {
        case 0:
          return this.getOverallData()
        case 1:
          return this.renderChart.apply(this, arguments)
        case 2:
          return this.renderTable()
      }
    },
    toChannelAnal () {
      this.$router.push('/report/channelAnal')
    },
    // 覆盖minix中方法
    getChartData (params = {}) {
      // 需要有默认指标
      const indicator = this.getSelectedIndic(params.indicator).map(t => t.value)
      return getReportData(this.getParameter({
        ...params,
        indicator
      }))
    },
    // 获取概览数据
    getOverallData () {
      this.loading1 = true
      const params = {
        ...this.queryParams,
        ...this.queryParams1
      }
      const { time_range } = params
      const d1 = new Date(time_range)
      const d2 = new Date(time_range)
      return Axios.all([
        // 查询当前日期
        this.getChartData({
          ...params,
          chart: 'base_time_table'
        }),
        // 查询上一个日期
        this.getChartData({
          ...params,
          chart: 'base_time_table',
          time_range: parseTime(this.yesterday, dateFmt)
        }),
        // 查询上一周日期
        this.getChartData({
          ...params,
          chart: 'base_time_table',
          time_range: parseTime(this.lastWeek, dateFmt)
        }),
        // 7日平均
        this.getChartData({
          ...params,
          chart: 'base_time_line',
          time_range: [parseTime(d1.setDate(d1.getDate() - 6), dateFmt), time_range],
          operation: 'resample',
          resample_rule: '7D',
          resample_method: 'mean'
        }),
        // 30日平均
        this.getChartData({
          ...params,
          chart: 'base_time_line',
          time_range: [parseTime(d2.setDate(d2.getDate() - 29), dateFmt), time_range],
          operation: 'resample',
          resample_rule: '30D',
          resample_method: 'mean'
        // eslint-disable-next-line sonarjs/cognitive-complexity
        })]).then(Axios.spread((res1, res2, res3, res4, res5) => {
        const cardList = this.getSelectedIndic(params.indicator).map(t => (
          {
            id: t.value, title: t.label, describe: t.describe, count: '', prevCount: '', lastCount: '', prevDay: '', prevWeek: '', average7: '', average30: ''
          }
        ))
        const fillVal = (tarList, resObj, key) => {
          for (const name in resObj) {
            const o = tarList.find(t => t.title === name)
            if (o) {
              o[key] = this.formatNumber(resObj[name], name)
            }
          }
        }
        res1.data.forEach(item => {
          const { result } = item
          if (!Array.isArray(result) || !result[0] || !Array.isArray(result[0].data)) return false
          result[0].data.forEach(obj => fillVal(cardList, obj, 'count'))
        })

        res2.data.forEach(item => {
          const { result } = item
          if (!Array.isArray(result) || !result[0] || !Array.isArray(result[0].data)) return false
          result[0].data.forEach(obj => fillVal(cardList, obj, 'prevCount'))
        })
        res3.data.forEach(item => {
          const { result } = item
          if (!Array.isArray(result) || !result[0] || !Array.isArray(result[0].data)) return false
          result[0].data.forEach(obj => fillVal(cardList, obj, 'lastCount'))
        })
        cardList.forEach(item => {
          if (/^\d+(\.\d+)?$/.test(item.count) && item.count) {
            if (/^\d+(\.\d+)?$/.test(item.prevCount)) {
              item.prevDay = toFixed((item.count - item.prevCount) / item.prevCount * 100, 2)
            }
            if (/^\d+(\.\d+)?$/.test(item.lastCount)) {
              item.prevWeek = toFixed((item.count - item.lastCount) / item.lastCount * 100, 2)
            }
          }
        })
        res4.data.forEach(item => {
          const { result } = item
          if (!Array.isArray(result) || !result[0] || !Array.isArray(result[0].data)) return
          result[0].data.forEach(obj => fillVal(cardList, obj, 'average7'))
        })
        res5.data.forEach(item => {
          const { result } = item
          if (!Array.isArray(result) || !result[0] || !Array.isArray(result[0].data)) return
          result[0].data.forEach(obj => fillVal(cardList, obj, 'average30'))
        })
        this.cardList = cardList
        this.setFoldBtnShow()
        this.loading1 = false
      })).catch(() => {})
    },
    // 图表渲染
    renderChart (flag) {
      this.loading4 = true
      const params = {
        ...this.queryParams,
        ...this.queryParams1
      }
      this.chartparams1 = {
        ...params,
        chart: 'base_time_table',
        order_by: 'time asc',
        time_grain_sqla: DATE_TYPE.HOUR,
        noUpdate: typeof flag === 'boolean' ? flag : false
      }
      return this.getChartData(this.chartparams1).then(res => {
        const list = (Array.isArray(res.data[0].result) && res.data[0].result[0].data) || []
        this.chartData1 = list
        this.legendData1 = this.getSelectedIndic(params.indicator).map(t => t.label)
        this.loading4 = false
      }).catch(() => {
        this.loading4 = false
      })
    },
    renderTable () {
      this.loading1 = true
      const params = {
        ...this.queryParams,
        ...this.queryParams1
      }
      const tableKeys = [{
        prop: 'index',
        label: '序号',
        width: 50,
        fixed: 'left',
        keepOrigin: true
      },
      {
        prop: 'time',
        label: '时间',
        minWidth: 140,
        fixed: 'left',
        keepOrigin: true,
        sortable: 'custom'
      }]
      tableKeys.push(...this.getSelectedIndic(params.indicator).map(({ label, value }) => {
        return {
          label,
          prop: value + '',
          minWidth: 50 + 15 * label.length + 'px',
          sortable: 'custom'
        }
      }))
      this.tableKeys1 = tableKeys
      const time_grain_sqla = DATE_TYPE.HOUR
      const { time_range } = params
      const date = new Date(time_range).getDate()

      return Axios.all([
        // 总数
        this.getChartData({
          ...params,
          chart: 'base_time_table'
        }),
        // 跟前一日对比
        this.getChartData({
          ...params,
          chart: 'base_time_table',
          time_range: parseTime(new Date(time_range).setDate(date - 1), dateFmt)
        }),
        // 跟上一周同星期对比
        this.getChartData({
          ...params,
          chart: 'base_time_table',
          time_range: parseTime(new Date(time_range).setDate(date - 7), dateFmt)
        }),
        // 查询当前日期
        this.getChartData({
          order_by: 'time asc',
          ...params,
          chart: 'base_time_table',
          time_grain_sqla: DATE_TYPE.HOUR
        })
      // eslint-disable-next-line sonarjs/cognitive-complexity
      ]).then(Axios.spread((res1, res2, res3, res4) => {
        const list = []

        const total1 = {}
        const total2 = {}
        const data1 = Array.isArray(res1.data[0].result) && res1.data[0].result[0].data[0]
        if (data1) {
          for (let name in data1) {
            total2[name] = total1[name] = data1[name]
          }
        }
        const data2 = Array.isArray(res2.data[0].result) && res2.data[0].result[0].data[0]
        if (data2) {
          for (const name in data2) {
            total1[name + '_pre'] = data2[name]
          }
        }
        const data3 = Array.isArray(res3.data[0].result) && res3.data[0].result[0].data[0]
        if (data3) {
          for (const name in data3) {
            total2[name + '_pre'] = data3[name]
          }
        }
        total1.time = '总（环比）'
        total2.time = '总（同比）'
        list.push(total1)
        list.push(total2)
        const data4 = Array.isArray(res4.data[0].result) && res4.data[0].result[0].data
        Array.isArray(data4) && list.push(...data4.map((item, index) => {
          const obj = {
            index: index + 1
          }
          for (let name in item) {
            let val = item[name]
            let key = name
            if (['__timestamp', 'time'].includes(name)) {
              key = 'time'
              val = this.fmtTableDate(val, time_grain_sqla)
            }
            key && (obj[key] = val)
          }
          return obj
        }))
        this.tableList1 = list
        this.loading1 = false
      })).catch(() => {})
    },
    // 指标详情
    indicatorDetail (item) {
      this.detail.indicator = item
      this.detail.params = {
        ...this.queryParams,
        time_range: this.queryParams1.time_range,
        time_grain_sqla: DATE_TYPE.HOUR
      }
      this.detail.visible = true
    },
    togglePattern ({ value }) {
      if (this.pattern === value) return
      this.pattern = value
      this.renderViewLayer()
    },
    indicatorChange () {
      localStorage.setItem('indicator', JSON.stringify(this.queryParams.indicator))
    },
    // 获取被选中的指标
    getSelectedIndic (selection) {
      // 指标选项
      let indic = []
      const indicators = this.indicatorList.slice()
      if (selection.includes(0)) {
        indic = indicators
      } else {
        if (selection.includes(-1) || !selection.length) {
          indic = indicators.filter(t => this.defIndicator.includes(t.value))
        }
        selection.forEach(val => {
          const obj = indicators.find(t => t.value === val)
          if (obj && indic.every(t => t.value !== val)) {
            indic.push(obj)
          }
        })
      }
      // 排序
      this.indicatorSort(indic, 'label')
      return indic
    },
    dateTypeChange () {
      const sqla = this.queryParams2.time_grain_sqla
      switch (sqla) {
        case 'P1D':
          this.timeRangeNum = this.timeRangeNumD
          break
        case 'P1W':
          this.timeRangeNum = this.timeRangeNumW
          break
        case 'P1M':
          this.timeRangeNum = this.timeRangeNumM
          break
      }
      this.renderChartLayer()
    },
    timeRangeNumChange () {
      const sqla = this.queryParams2.time_grain_sqla
      switch (sqla) {
        case 'P1D':
          this.timeRangeNumD = this.timeRangeNum
          break
        case 'P1W':
          this.timeRangeNumW = this.timeRangeNum
          break
        case 'P1M':
          this.timeRangeNumM = this.timeRangeNum
          break
      }
      this.renderChartLayer()
    },
    // 时间分层趋势图
    async renderChartLayer (flag = false) {
      this.loading5 = true
      const params = {
        ...this.queryParams,
        ...this.queryParams2
      }
      const timeRange = this.getFinalDateRange(params, this.timeRangeNum)
      let filters = `app_id in (${params.app_id})`
      if (params.version.length) {
        filters += ` and version in (${params.version})`
      }
      if (params.union_id.length) {
        filters += ` and union_id in (${params.union_id})`
      }
      if (params.attr_id.length) {
        filters += ` and attr_id in (${params.attr_id})`
      }
      this.chartparams2 = {
        time_grain_sqla: params.time_grain_sqla,
        filters,
        time_range: `${timeRange[0] + 'T00:00:00'} : ${timeRange[1] + 'T23:59:59'}`
      }
      const queryParams = {
        'data_source': this.metricsGroup.data_source,
        queries: [{
          filters,
          'granularity': this.metricsGroup.granularity,
          indicator: params.indicator.join(','),
          time_grain_sqla: params.time_grain_sqla,
          time_range: `${timeRange[0] + 'T00:00:00'} : ${timeRange[1] + 'T23:59:59'}`
          // chart: 'base_time_table',
          // order_by: 'time asc'
        }, {
          filters,
          'granularity': this.metricsGroup.granularity,
          indicator: params.indicator.join(','),
          time_grain_sqla: params.time_grain_sqla,
          time_range: `${timeRange[2] + 'T00:00:00'} : ${timeRange[3] + 'T23:59:59'}`
          // chart: 'base_time_table',
          // order_by: 'time asc'
        }]
      }
      await getReportDatas(queryParams).then(res => {
        const result = (Array.isArray(res.data[0].result) && res.data[0].result) || [{}, {}]
        const contrastList = result[1].data || []
        const list = (result[0].data || []).map((item, index) => {
          item.contrast = contrastList[index] || {}
          return item
        })
        this.chartData2 = list
        this.indicatorData = {}

        this.legendData2 = this.getSelectedIndic(params.indicator).map(t => t.label)
        this.loading5 = false
      }).catch(() => {
        this.loading5 = false
      })
      return this.legendChang()
    },
    getChartOption (list, selectLegend, params) {
      const legend = this.getSelectedIndic(params.indicator).map(t => t.label)
      return {
        tooltip: {
          trigger: 'axis'
        },
        legend: {
          bottom: 0,
          type: 'scroll',
          icon: 'circle',
          data: legend,
          selected: legend.reduce((obj, label) => {
            obj[label] = selectLegend.includes(label)
            return obj
          }, {})
        },
        grid: {
          left: '3%',
          right: '3%',
          bottom: '10%',
          containLabel: true
        },
        xAxis: {
          type: 'category',
          boundaryGap: false,
          data: list.map(t => this.fmtTableDate(t.time, params.time_grain_sqla)),
          axisLabel: {
            formatter (value) {
              return params.time_grain_sqla === DATE_TYPE.HOUR ? value.slice(11) : value
            }
          }
        },
        yAxis: selectLegend.map(name => ({
          type: 'value',
          name,
          axisLabel: {
            // y轴上带的单位
            formatter: '{value}'
          },
          // 轴线
          axisLine: {
            show: true
          },
          // 分割线
          splitLine: {
            show: false
          }
        })),
        series: list.reduce((arr, item) => {
          for (const key in item) {
            if (key === 'time') continue
            const it = arr.find(t => t.name === key)
            const val = this.formatNumber(item[key], key)
            if (it) {
              it.data.push(val)
            } else {
              const obj = {
                name: key,
                type: 'line',
                data: [val]
              }
              const index = selectLegend.findIndex(label => label === key)
              index !== -1 && (obj.yAxisIndex = index)
              arr.push(obj)
            }
          }
          return arr
        }, [])
      }
    },
    // 时间分层数据表
    renderTableLayer () {
      this.loading3 = true
      const params = {
        ...this.queryParams,
        ...this.queryParams3
      }
      const tableKeys = [{
        prop: 'index',
        label: '序号',
        width: 50,
        fixed: 'left',
        keepOrigin: true
      },
      {
        prop: 'time',
        label: '时间',
        minWidth: 140,
        fixed: 'left',
        keepOrigin: true,
        sortable: 'custom'
      }]
      tableKeys.push(...this.getSelectedIndic(params.indicator).map(({ label, value, totalHide }) => {
        return {
          label,
          prop: value + '',
          minWidth: 50 + 15 * label.length + 'px',
          sortable: 'custom',
          totalHide
        }
      }))
      this.tableKeys2 = tableKeys
      const timeRange = this.getFinalDateRange(params)
      const dayDiff1 = (new Date(timeRange[1]).getTime() - new Date(timeRange[0]).getTime()) / 1000 / 60 / 60 / 24 + 1
      const prevTimeRange = this.getLastPeriod(params)
      const dayDiff2 = (new Date(prevTimeRange[1]).getTime() - new Date(prevTimeRange[0]).getTime()) / 1000 / 60 / 60 / 24 + 1
      Axios.all([
        // 总体
        this.getChartData({
          ...params,
          chart: 'big_number',
          operation: 'resample',
          resample_rule: dayDiff1 + 'D',
          resample_method: 'sum'
        }),
        // 日均
        this.getChartData({
          ...params,
          chart: 'base_time_line',
          operation: 'resample',
          resample_rule: dayDiff1 + 'D',
          resample_method: 'mean'
        }),
        // 查询当前周期
        this.getChartData({
          ...params,
          chart: 'base_time_table'
        }),
        // 上一周期总体
        this.getChartData({
          ...params,
          chart: 'big_number',
          operation: 'resample',
          resample_rule: dayDiff2 + 'D',
          resample_method: 'sum',
          time_range: prevTimeRange
        }),
        // 上一周期平均
        this.getChartData({
          ...params,
          chart: 'base_time_line',
          operation: 'resample',
          resample_rule: dayDiff2 + 'D',
          resample_method: 'mean',
          time_range: prevTimeRange
        })
      // eslint-disable-next-line sonarjs/cognitive-complexity
      ]).then(Axios.spread((res1, res2, res3, res4, res5) => {
        const { time_grain_sqla } = params
        const list = []
        const total1 = {
          time: '总体（环比）'
        }

        const dateTypeMap = {
          [DATE_TYPE.DAY]: '日',
          [DATE_TYPE.WEEK]: '周',
          [DATE_TYPE.MONTH]: '月'
        }
        const total2 = {
          time: `${dateTypeMap[time_grain_sqla]}均（环比）`
        }
        const data1 = Array.isArray(res1.data[0].result) && res1.data[0].result[0].data[0]
        if (data1) {
          for (const name in data1) {
            total1[name] = data1[name]
          }
        }
        const data2 = Array.isArray(res2.data[0].result) && res2.data[0].result[0].data[0]
        if (data2) {
          for (const name in data2) {
            total2[name] = data2[name]
          }
        }
        const data4 = Array.isArray(res4.data[0].result) && res4.data[0].result[0].data[0]
        if (data4) {
          for (const name in data4) {
            total1[name + '_pre'] = data4[name]
          }
        }
        const data5 = Array.isArray(res5.data[0].result) && res5.data[0].result[0].data[0]
        if (data5) {
          for (const name in data5) {
            total2[name + '_pre'] = data5[name]
          }
        }
        list.push(total1)
        list.push(total2)
        const data3 = Array.isArray(res3.data[0].result) && res3.data[0].result[0].data
        Array.isArray(data3) && list.push(...data3.map((item, index) => {
          const obj = {
            index: index + 1
          }
          for (let name in item) {
            let val = item[name]
            let key = name
            if (['__timestamp', 'time'].includes(name)) {
              key = 'time'
              // 记录时间
              obj.stamp = val
              val = this.fmtTableDate(val, time_grain_sqla)
            } else {
              // val = this.formatNumber(val, name)
              if (key && isNumber(val)) {
                obj['warn_' + key] = val < total2[key]
              }
            }
            key && (obj[key] = val)
          }
          return obj
        }))
        this.tableList2 = list
        this.loading3 = false
      })).catch(() => {
      })
    },
    async legendChang (val) {
      const list = []
      val = val || this.legendList
      this.legendList = val
      val.forEach(name => {
        const item = this.indicatorMap1.get(name)
        if (!this.indicatorData[item.ID]) {
          list.push({
            granularity: this.metricsGroup.granularity,
            indicator: item.ID + '',
            'group_by': 'union_id',
            'order_by': `${item.ID} desc`,
            filters: this.chartparams2.filters,
            time_range: this.chartparams2.time_range,
            row_limit: 3
          })
        }
      })
      if (list.length) {
        await getReportDatas({ data_source: this.metricsGroup.data_source, queries: list }).then(res => {
          const result = (Array.isArray(res.data[0].result) && res.data[0].result) || []
          result.map((item, index) => {
            this.indicatorData[list[index].indicator] = item.data
          })
        })
      }
      this.unionGroupData = val.map(name => {
        const item = this.indicatorMap1.get(name)
        return {
          name,
          value: this.indicatorData[item.ID]
        }
      })
    },
    // 详情查看
    viewDetails (item) {
      this.particular.params = {
        ...this.queryParams,
        indicator: item.prop,
        time_range: this.queryParams3.time_range
      }
      this.particular.indicator = {
        id: item.prop,
        title: item.label
      }
      this.particular.visible = true
    },
    sortChange ({ column, prop, order }, type) {
      const order_by = order ? prop + ' ' + order.slice(0, -6) : ''
      if (type === 1) {
        this.queryParams1 = {
          ...this.queryParams1,
          order_by
        }
        this.renderViewLayer()
      } else {
        this.queryParams3 = {
          ...this.queryParams3,
          order_by
        }
        this.renderTableLayer()
      }
    },
    setFoldBtnShow () {
      this.$nextTick(() => {
        this.foldBtnShow = this.$refs.cardList && parseInt(this.$refs.cardList.offsetWidth / 300) * 2 < this.cardList.length
      })
    },
    cellClassName ({ row, column, rowIndex, columnIndex }) {
      const val = row[column.label]
      let classname = []
      if (rowIndex >= 2) {
        if (columnIndex === 1) {
          // if (row.stamp && [0, 6].includes(new Date(row.stamp).getDay())) classname.push('weekend')
        } else if (columnIndex > 1) {
          const meanVal = this.tableList2[1][column.label]
          if (isNumber(val) && val < meanVal) {
            classname.push('warning')
          }
        }
      }
      return classname.join(' ')
    },
    // 导出
    async  exportExcel1 () {
      this.btnLoading1 = true
      await exportDoc.excel(`指标概览（${this.queryParams1.time_range}）`, this.handleExportTable, {
        tableList: this.tableList1,
        tableKeys: this.tableKeys1
      })
      this.btnLoading1 = false
    },
    // 导出
    exportExcel2 () {
      exportDoc.excel(`时间分层数据表（${this.queryParams3.time_range.join('~')}）`, this.handleExportTable, {
        tableList: this.tableList2,
        tableKeys: this.tableKeys2
      })
    },
    handleExportTable (sheet, execlName, { tableList, tableKeys }) {
      sheet.range(`A1:${exportDoc.getColName(tableKeys.length - 1)}1`).merged(true).value(execlName).style({
        fontSize: 18,
        fontFamily: '微软雅黑',
        horizontalAlignment: 'center',
        verticalAlignment: 'center'
      })
      const rangeStyle = {
        fontSize: 14,
        fontFamily: '微软雅黑',
        horizontalAlignment: 'center',
        verticalAlignment: 'center'
      }
      tableKeys.forEach((item, index) => {
        sheet.cell(`${exportDoc.getColName(index)}2`).value(item.label).style(rangeStyle)
        sheet.column(exportDoc.getColName(index)).width(index === 0 ? 10 : 20)
      })
      const rangeStyleText = {
        fontSize: 14,
        fontFamily: '宋体',
        horizontalAlignment: 'center',
        verticalAlignment: 'center'
      }
      // eslint-disable-next-line sonarjs/cognitive-complexity
      tableList.map((item, index) => {
        const rowIndex = index + 3
        tableKeys.forEach((it, i) => {
          let val = it.prop === 'time' ? item[it.prop] : this.formatNumber(item[it.label], it.label)
          it.label.includes('率') && (val = val + '%')
          if ([0, 1].includes(index)) {
            if (i === 1) {
              sheet.range(`${exportDoc.getColName(i - 1)}${rowIndex}:${exportDoc.getColName(i)}${rowIndex}`).merged(true).value(val).style(rangeStyleText)
            } else if (i !== 0) {
              if (!index && EXINDICATORS.includes(it.label)) {
                sheet.cell(`${exportDoc.getColName(i)}${rowIndex}`).value('').style(rangeStyleText)
              } else {
                let v = val
                const pre = item[it.label + '_pre']
                const suffix = toFixed((item[it.label] - pre) / pre * 100, 2)
                v += `(${suffix >= 0 ? '+' + suffix : suffix}%)`
                sheet.cell(`${exportDoc.getColName(i)}${rowIndex}`).value(v).style(rangeStyleText)
              }
            }
          } else {
            sheet.cell(`${exportDoc.getColName(i)}${rowIndex}`).value(val).style(rangeStyleText)
          }
        })
      })
    },
    // 全屏切换
    screenChange (full, type) {
      // this['maxHeight' + type] = full ? this.$refs['content' + type].offsetHeight - 60 : 400
      this.isFullScreen = full
    },
    fmtNumer (val, label = '') {
      if (!/^(-?\d+)(\.\d+)?$/.test(val)) return '-'
      if (label === true || (typeof label === 'string' && label.includes('率'))) {
        val = val + '%'
      } else {
        val = numToText(val)
      }
      return val
    },
    formatDate (val, fmt) {
      return parseTime(val, fmt)
    },
    rowClassName ({ row, rowIndex }) {
      if ([0, 1].includes(rowIndex)) return 'emphasize'
      return ''
    },
    rowClassName2 ({ row, rowIndex }) {
      const classname = []
      if ([0, 1].includes(rowIndex)) {
        classname.push('emphasize')
      } else if (row.stamp && [0, 6].includes(new Date(row.stamp).getDay())) {
        classname.push('weekend')
      }
      return classname.join(' ')
    },
    getChannels () {
      const list = this.permission_projectList.map(item => item.app_id)
      return getChannelByAppId({
        app_ids: list.join()
      }).then(res => {
        this.channelList = res.data.list.map(item => {
          item.name = `${item.name}(${item.channel_id})`
          return item
        })
      })
    },
    getAllRights () {
      Axios.all([listRightPackage({ page: 1, page_size: 100, status: 10 }), getRightPackage()]).then(Axios.spread((res1, res2) => {
        const rightMap = (res1.data.list || []).reduce((map, t) => {
          map[t.pkg_id] = t.package_id
          return map
        }, {})
        this.allpackages = (res2.data.list || []).map(t => ({
          ...t,
          label: t.name,
          value: rightMap[t.pkg_id]
        })).filter(t => t.value)
      }))
    },
    getVerLists (app_id) {
      getVersionTree({ app_id, is_test: false })
        .then(res => {
          let list = res.data || []
          this.versionOpts = list
        })
    }
  },
  computed: {
    ...mapGetters('zcsd-core', ['permission_projectList']),
    // 默认选中指标
    defIndicator () {
      return this.indicatorList.filter(t => defIndicator.includes(t.label)).map(t => t.value)
    },
    yesterday () {
      const { time_range } = this.queryParams1
      if (!time_range) return ''
      const d = new Date(time_range)
      d.setDate(d.getDate() - 1)
      return d
    },
    lastWeek () {
      const { time_range } = this.queryParams1
      if (!time_range) return ''
      const d = new Date(time_range)
      d.setDate(d.getDate() - 7)
      return d
    },
    packageOpts () {
      let { app_id: appId } = this.queryParams
      if (!appId) return []
      appId = parseInt(appId)
      return this.allpackages.filter(t => t.app_id === appId)
    }
  }
}
</script>

<style lang="scss" scoped>
.overview-wrap {
  display: flex;
  color: #333;
  padding: 16px;
  overflow: hidden;
  flex-direction: column;
  background-color: #eee;
  .terms {
    padding: 12px;
    margin-bottom: 16px;
    background-color: #fff;
    .condition {
      margin-top: 12px;
      overflow: hidden;
      transition: height .3s ease-in-out;
      justify-content: space-between;
    }
  }
  .scroll {
    flex: 1;
    overflow-y: auto;
  }
  .section {
    padding: 12px;
    margin-bottom: 16px;
    background-color: #fff;
    min-height: 652px;
    .content {
      min-height: 446px;
    }
    .chart-wrap {
      height: 446px;
      margin-top: 10px;
    }
  }
  .section3 .table-list /deep/ .cell-text {
    &:hover {
      color: #409eff;
    }
  }
  .headline {
    display: flex;
    align-items: center;
    margin:0 -12px 10px;
    padding: 8px 12px;
    border-bottom: 1px solid #ddd;
    justify-content: space-between;
    .title {
      font-size: 18px;
      font-weight: bold;
      .export {
        margin-left: 6px;
        cursor: pointer;
        &:hover {
          color: #409eff;
        }
      }
      .tips {
        margin-left: 10px;
        font-size: 14px;
        color: #909399;
        font-weight: normal;
      }
    }
    .patterns {
      display: flex;
      .pattern {
        padding: 6px 8px;
        cursor: pointer;
        .svg-icon {
          font-size: 20px;
        }
        &:hover {
          .svg-icon {
            color: #00bbd7;
          }
        }
        &.active {
          .svg-icon {
            color: #409eff;
          }
        }
      }
    }
  }
  .condition {
    // float: right;
    // display: flex;
    // align-items: center;
    // justify-content: flex-end;
    .filters {
      .filter {
        margin-right: 20px;
        &:last-of-type {
          margin-right: 0;
        }
        .label {
          margin-right: 10px;
        }
      }
    }
    .export {
      margin-right: 10px;
    }
    .date-filter {
      display: flex;
      align-items: center;
      justify-content: flex-end;
      .label {
        margin-right: 10px;
      }
    }
  }
  .card-wrap {
    padding: 16px 20px 10px;
  }
  .card-list {
    display: flex;
    flex-wrap: wrap;
    margin-right: -14px;
    overflow: hidden;
    &.fold {
      max-height: 420px;
    }
    .card-box {
      flex: 300px 0 0;
      height: 200px;
      padding: 16px 20px 0;
      margin-right: 14px;
      margin-bottom: 14px;
      border-radius: 4px;
      border: 1px solid rgba($color: #000, $alpha: 0.05);
      box-shadow: 2px 2px 4px 0px rgba($color: #000, $alpha: 0.3);
    }
    .card-top {
      display: flex;
      margin-bottom: 6px;
      justify-content: space-between;
      .title {
        font-size: 16px;
        cursor: pointer;
        &:hover {
          color: #1890ff;
        }
      }
    }
    .count {
      color: #000;
      font-size: 30px;
    }
    .trend {
      display: flex;
      height: 30px;
      line-height: 30px;
      margin-top: 30px;
      margin-bottom: 10px;
      border-bottom: 1px solid #eee;
      justify-content: space-between;
      .trend_item {
        display: flex;
        align-items: center;
        min-width: 100px;
      }
      .label {
        white-space: nowrap;
      }
      .rise {
        margin: 0 6px;
        border-width: 6px;
        border-style: solid;
        transform: translateY(-25%);
        border-color: transparent transparent #2dca93 transparent;
        &.decline {
          transform: translateY(25%);
          border-color: #fc6772 transparent transparent transparent;
        }
      }
    }
    .average {
      line-height: 1.5;
      .num {
        margin-left: 30px;
      }
    }
  }
  .fold-box {
    display: flex;
    padding: 6px 0;
    justify-content: flex-end;
    .fold {
      display: flex;
      font-size: 16px;
      cursor: pointer;
      align-items: center;
      &:hover {
        color: #00bbd7;
        .mark {
          border-bottom-color: #00bbd7;
        }
      }
      .mark {
        margin: 0 6px;
        border-width: 6px;
        border-style: solid;
        transition: all 0.3s;
        transform: translateY(-25%);
        border-color: transparent transparent rgba($color: #000, $alpha: 0.5)
          transparent;
        &.fold {
          transform: rotate(180deg) translateY(-25%);
        }
      }
    }
  }
}
</style>
<style lang="scss">
.el-popover {
  &.checkbox-group {
    .el-checkbox {
      display: block;
      margin: 4px 0;
    }
    .divider {
      margin: 4px 0;
      height: 1px;
      background-color: #ddd;
    }
    .el-checkbox-group {
      max-height: 200px;
      overflow-x: hidden;
      overflow-y: auto;
    }
  }
}
</style>
